home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / mips / include / asm / mc146818-time.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  3.7 KB  |  120 lines

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Machine dependent access functions for RTC registers.
  7.  */
  8. #ifndef __ASM_MC146818_TIME_H
  9. #define __ASM_MC146818_TIME_H
  10.  
  11. #include <linux/bcd.h>
  12. #include <linux/mc146818rtc.h>
  13. #include <linux/time.h>
  14.  
  15. /*
  16.  * For check timing call set_rtc_mmss() 500ms; used in timer interrupt.
  17.  */
  18. #define USEC_AFTER    500000
  19. #define USEC_BEFORE    500000
  20.  
  21. /*
  22.  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
  23.  * called 500 ms after the second nowtime has started, because when
  24.  * nowtime is written into the registers of the CMOS clock, it will
  25.  * jump to the next second precisely 500 ms later. Check the Motorola
  26.  * MC146818A or Dallas DS12887 data sheet for details.
  27.  *
  28.  * BUG: This routine does not handle hour overflow properly; it just
  29.  *      sets the minutes. Usually you'll only notice that after reboot!
  30.  */
  31. static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
  32. {
  33.     int real_seconds, real_minutes, cmos_minutes;
  34.     unsigned char save_control, save_freq_select;
  35.     int retval = 0;
  36.     unsigned long flags;
  37.  
  38.     spin_lock_irqsave(&rtc_lock, flags);
  39.     save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
  40.     CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
  41.  
  42.     save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
  43.     CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
  44.  
  45.     cmos_minutes = CMOS_READ(RTC_MINUTES);
  46.     if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
  47.         cmos_minutes = bcd2bin(cmos_minutes);
  48.  
  49.     /*
  50.      * since we're only adjusting minutes and seconds,
  51.      * don't interfere with hour overflow. This avoids
  52.      * messing with unknown time zones but requires your
  53.      * RTC not to be off by more than 15 minutes
  54.      */
  55.     real_seconds = nowtime % 60;
  56.     real_minutes = nowtime / 60;
  57.     if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
  58.         real_minutes += 30;        /* correct for half hour time zone */
  59.     real_minutes %= 60;
  60.  
  61.     if (abs(real_minutes - cmos_minutes) < 30) {
  62.         if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  63.             real_seconds = bin2bcd(real_seconds);
  64.             real_minutes = bin2bcd(real_minutes);
  65.         }
  66.         CMOS_WRITE(real_seconds, RTC_SECONDS);
  67.         CMOS_WRITE(real_minutes, RTC_MINUTES);
  68.     } else {
  69.         printk(KERN_WARNING
  70.                "set_rtc_mmss: can't update from %d to %d\n",
  71.                cmos_minutes, real_minutes);
  72.         retval = -1;
  73.     }
  74.  
  75.     /* The following flags have to be released exactly in this order,
  76.      * otherwise the DS12887 (popular MC146818A clone with integrated
  77.      * battery and quartz) will not reset the oscillator and will not
  78.      * update precisely 500 ms later. You won't find this mentioned in
  79.      * the Dallas Semiconductor data sheets, but who believes data
  80.      * sheets anyway ...                           -- Markus Kuhn
  81.      */
  82.     CMOS_WRITE(save_control, RTC_CONTROL);
  83.     CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
  84.     spin_unlock_irqrestore(&rtc_lock, flags);
  85.  
  86.     return retval;
  87. }
  88.  
  89. static inline unsigned long mc146818_get_cmos_time(void)
  90. {
  91.     unsigned int year, mon, day, hour, min, sec;
  92.     unsigned long flags;
  93.  
  94.     spin_lock_irqsave(&rtc_lock, flags);
  95.  
  96.     do {
  97.         sec = CMOS_READ(RTC_SECONDS);
  98.         min = CMOS_READ(RTC_MINUTES);
  99.         hour = CMOS_READ(RTC_HOURS);
  100.         day = CMOS_READ(RTC_DAY_OF_MONTH);
  101.         mon = CMOS_READ(RTC_MONTH);
  102.         year = CMOS_READ(RTC_YEAR);
  103.     } while (sec != CMOS_READ(RTC_SECONDS));
  104.  
  105.     if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
  106.         sec = bcd2bin(sec);
  107.         min = bcd2bin(min);
  108.         hour = bcd2bin(hour);
  109.         day = bcd2bin(day);
  110.         mon = bcd2bin(mon);
  111.         year = bcd2bin(year);
  112.     }
  113.     spin_unlock_irqrestore(&rtc_lock, flags);
  114.     year = mc146818_decode_year(year);
  115.  
  116.     return mktime(year, mon, day, hour, min, sec);
  117. }
  118.  
  119. #endif /* __ASM_MC146818_TIME_H */
  120.